package com.cloudfast.dingtalk;

import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import com.cloudfast.context.error.CloudException;
import com.cloudfast.context.error.ErrorCode;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiGettokenRequest;
import com.dingtalk.api.request.OapiServiceGetCorpTokenRequest;
import com.dingtalk.api.request.OapiSnsGetuserinfoBycodeRequest;
import com.dingtalk.api.request.OapiUserGetbyunionidRequest;
import com.dingtalk.api.request.OapiUserGetuserinfoRequest;
import com.dingtalk.api.request.OapiV2UserGetRequest;
import com.dingtalk.api.response.OapiGettokenResponse;
import com.dingtalk.api.response.OapiServiceGetCorpTokenResponse;
import com.dingtalk.api.response.OapiSnsGetuserinfoBycodeResponse;
import com.dingtalk.api.response.OapiUserGetbyunionidResponse;
import com.dingtalk.api.response.OapiUserGetuserinfoResponse;
import com.dingtalk.api.response.OapiV2UserGetResponse;
import com.dingtalk.api.response.OapiV2UserGetResponse.UserGetResponse;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.taobao.api.ApiException;

/**
 * 钉钉交互类
 *
 * @author liuyw
 * @date 2022年9月11日
 */
public class CloudDingTalk {

    /**
     * 企业内应用标识
     */
    private static final String APP_ENTERPRICE = "enterprise";

    /**
     * 获取token
     *
     * @param corpId    企业码
     * @param appKey    项目key
     * @param appSecret 项目secret
     * @param appTicket 第三方ticket
     * @param appScope  企业内/第三方应用
     * @return
     */
    public String getAccessToken(String corpId, String appKey, String appSecret, String appTicket, String appScope) {
        // 企业内获取accessToken
        if (appScope.equalsIgnoreCase(APP_ENTERPRICE)) {
            return enterPriceToken(appKey, appSecret);
            // 企业外 获取accessToken
        } else if (StringUtils.isEmpty(appTicket)) {
            throw new CloudException(ErrorCode.TICKET_NULL);
        }
        return thirdToken(corpId, appKey, appSecret, appTicket);
    }

    /**
     * 获取用户信息
     *
     * @param code
     * @param accessToken
     * @return
     * @throws ApiException
     */
    @SuppressWarnings("unchecked")
    public Map<String, Object> getUserInfoByTempCode(String code, String accessToken) {
        try {
            DingTalkClient client = new DefaultDingTalkClient(DingTalkURI.URL_GET_USER_INFO);
            OapiUserGetuserinfoRequest request = new OapiUserGetuserinfoRequest();
            request.setHttpMethod("GET");
            request.setCode(code);
            OapiUserGetuserinfoResponse response = client.execute(request, accessToken);
            if (!response.isSuccess()) {
                throw new CloudException(ErrorCode.GET_DING_TALK_USER_ERROR);
            }
            ObjectMapper mapper = new ObjectMapper();
            mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
            Map<String, Object> result = mapper.readValue(response.getBody(), Map.class);
            return (Map<String, Object>) result.get("result");

        } catch (Exception e) {
            throw new CloudException(ErrorCode.GET_DING_TALK_USER_ERROR);
        }
    }

    /**
     * 根据userid获取用户详情
     *
     * @param userid
     * @param accessToken
     * @return
     * @throws ApiException
     */
    public UserGetResponse getUserGetResponse(String userid, String accessToken) throws ApiException {
        DingTalkClient userDetailClient = new DefaultDingTalkClient(DingTalkURI.USER_INFO_DETAIL);
        OapiV2UserGetRequest req = new OapiV2UserGetRequest();
        req.setHttpMethod("post");
        req.setUserid(userid);
        OapiV2UserGetResponse rsp = userDetailClient.execute(req, accessToken);
        return rsp.getResult();
    }

    /**
     * 通过 认证code 获取 unionid
     *
     * @param authCode
     * @param appKey
     * @param appSecret
     * @return
     * @throws ApiException
     */
    public String getUnionid(String authCode, String appKey, String appSecret) throws ApiException {
        DefaultDingTalkClient client2 = new DefaultDingTalkClient(DingTalkURI.GET_UNIONID);
        OapiSnsGetuserinfoBycodeRequest reqBycodeRequest = new OapiSnsGetuserinfoBycodeRequest();

        reqBycodeRequest.setTmpAuthCode(authCode);
        OapiSnsGetuserinfoBycodeResponse bycodeResponse = client2.execute(reqBycodeRequest, appKey, appSecret);

        return bycodeResponse.getUserInfo().getUnionid();
    }

    /**
     * 根据unionid 获取userid
     *
     * @param unionid
     * @param access_token
     * @return
     * @throws ApiException
     */
    public String getUserId(String unionid, String access_token) throws ApiException {
        DingTalkClient clientDingTalkClient = new DefaultDingTalkClient(DingTalkURI.GET_USERID_UNIONID);
        OapiUserGetbyunionidRequest reqGetbyunionidRequest = new OapiUserGetbyunionidRequest();
        reqGetbyunionidRequest.setUnionid(unionid);
        OapiUserGetbyunionidResponse oapiUserGetbyunionidResponse = clientDingTalkClient.execute(reqGetbyunionidRequest,
                access_token);
        // 根据userId获取用户信息
        return oapiUserGetbyunionidResponse.getResult().getUserid();
    }

    /**
     * 企业内token
     *
     * @param appKey
     * @param appSecret
     * @return
     */
    private String enterPriceToken(String appKey, String appSecret) {
        String token = null;
        DefaultDingTalkClient client = new DefaultDingTalkClient(DingTalkURI.ENTERPRICETOKEN);
        OapiGettokenRequest request = new OapiGettokenRequest();
        request.setCorpid(appKey);
        request.setCorpsecret(appSecret);
        request.setHttpMethod("GET");
        try {
            OapiGettokenResponse response = client.execute(request);
            String errMsg = response.getErrmsg();
            if ("ok".equals(errMsg)) {
                token = response.getAccessToken();
            }
        } catch (ApiException e1) {
            return token;
        }
        return token;
    }

    /**
     * 第三方认证token
     *
     * @param corpId
     * @param appKey
     * @param appSecret
     * @param app
     * @return
     */
    public String thirdToken(String corpId, String appKey, String appSecret, String app) {
        try {
            DefaultDingTalkClient client = new DefaultDingTalkClient(DingTalkURI.THIREDAPPTOKEN);
            OapiServiceGetCorpTokenRequest req = new OapiServiceGetCorpTokenRequest();
            req.setAuthCorpid(corpId);
            OapiServiceGetCorpTokenResponse execute = client.execute(req, appKey, appSecret, appSecret);
            return execute.getAccessToken();
        } catch (ApiException e) {
            throw new CloudException(ErrorCode.NO_TICKET_SYSTEM_ERROR);
        }
    }
}
